const express = require('express');
const app = express();

// 安装并导入 JWT 相关的两个包，分别是 jsonwebtoken 和 express-jwt
const jwt = require('jsonwebtoken');
const { expressjwt: expressjwt } = require("express-jwt");

// 允许跨域资源共享
const cors = require('cors')
app.use(cors())

// 解析 post json数据的中间件
app.use(express.json())

// 解析 post 表单数据的中间件
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({extended: false }))

// TODO_02：定义 secret 密钥，建议将密钥命名为 secretKey
const secretKey = 'dm No1 ^_^'

// TODO_04：注册将 JWT 字符串解析还原成 JSON 对象的中间件
// 注意：只要配置成功了 express-jwt 这个中间件，就可以把解析出来的用户信息，挂载到 req.user 属性上
// 注意：只要配置成功了 express-jwt 这个中间件，就可以把解析出来的用户信息，挂载到 req.user 属性上
// 注意：只要配置成功了 express-jwt 这个中间件，就可以把解析出来的用户信息，挂载到 req.user 属性上
app.use(expressjwt({ secret: secretKey,algorithms: ["HS256"]  }).unless({ path: [/^\/api\//] }))

app.use((req,res,next) => {
    let reg = new RegExp(/^\/api\//,'g')
    if (reg.test(req.url)) {
        next()
        return
    }
    let tokenStr = req.headers.authorization.replace('Bearer ','')
    jwt.verify(tokenStr, secretKey, (err,decoded) => {
        if (err) {
            throw new Error('jwt的错误：'+err.message)
        }
        req.user = decoded
        console.log(req.user)
        next()
    })
})

app.post('/api/post',(req,res)=>{
    // 将 req.body 请求体中的数据，转存为 userinfo 常量
    const userinfo = req.body
    // 登录失败
    if (userinfo.username !== 'admin' || userinfo.password !== '000000') {
        return res.send({
            status: 400,
            message: '登录失败！',
        })
    }
    // 登录成功
    // TODO_03：在登录成功之后，调用 jwt.sign() 方法生成 JWT 字符串。并通过 token 属性发送给客户端
    // 参数1：用户的信息对象
    // 参数2：加密的秘钥
    // 参数3：配置对象，可以配置当前 token 的有效期
    // 记住：千万不要把密码加密到 token 字符中
    console.log('user',{username:userinfo.username})
    const token = jwt.sign({username:userinfo.username}, secretKey, { expiresIn: '120s' })
    res.send({
        status: 200,
        message: '登录成功！',
        token: token, // 要发送给客户端的 token 字符串
    })
})

// 这是一个有权限的 API 接口
app.get('/admin/getinfo', function (req, res) {
    // TODO_05：使用 req.user 获取用户信息，并使用 data 属性将用户信息发送给客户端
    // let tokenStr = req.headers.authorization.replace('Bearer ','')
    // jwt.verify(tokenStr, secretKey, (err,decoded) => {
    //     if (err) {
    //         throw new Error('jwt的错误：'+err.message)
    //     }
    //     req.user = decoded
    //     console.log(req.user)
    //     res.send({
    //         status: 200,
    //         message: '获取用户信息成功！',
    //         data: req.user, // 要发送给客户端的用户信息
    //     })
    // })

        console.log(req.user)
        res.send({
            status: 200,
            message: '获取用户信息成功2！',
            data: req.user, // 要发送给客户端的用户信息
        })
})

// TODO_06：使用全局错误处理中间件，捕获解析 JWT 失败后产生的错误
app.use((err,req,res,next)=>{
    // 注意：一定要把错误处理函数放在所有路由的前面，否则因为路由匹配不到，会跳过后面的所有错误处理函数，导致错误无法被处理
    // 注意：一定要把错误处理函数放在所有路由的前面，否则因为路由匹配不到，会跳过后面的所有错误处理函数，导致错误无法被处理

    // 这次错误是由 token 解析失败导致的
    if (err.name === 'UnauthorizedError') {
        return res.send({
            status: 401,
            message: '无效的token！',
        })
    }
    return res.send({
        status: 500,
        message: '未知的错误',
    })
})
app.listen(8989, ()=>console.log('listening on http://localhost:8989'))